#pragma once

#include <boost/describe.hpp>
#include <boost/serialization/singleton.hpp>

#include <oneapi/tbb/concurrent_unordered_map.h>
#include <openvino/runtime/compiled_model.hpp>
#include <openvino/runtime/core.hpp>

#include <oneapi/tbb.h>

#include <filesystem>
#include <string>

namespace solar::dnn::openvino
{
    enum class DeviceType : std::uint8_t
    {
        CPU,
        GPU,
    };
    BOOST_DESCRIBE_ENUM(DeviceType, CPU, GPU)

    class CompiledModelCache : public boost::serialization::singleton<CompiledModelCache>
    {
        public:
            auto getCompiledModel(std::string_view model_path,
                                  DeviceType device_type) -> ov::CompiledModel&;
            void clear();

        private:
            void updateCompiledModel(std::string_view model_path, DeviceType device_type);

            struct ModelState
            {
                    std::filesystem::file_time_type last_write_time_;
                    std::shared_ptr<ov::Model> model_;
            };
            ov::Core core_engine_;

            oneapi::tbb::concurrent_unordered_map<
                std::string, oneapi::tbb::concurrent_unordered_map<DeviceType, ov::CompiledModel>>
                compiled_model_cache_;
            oneapi::tbb::concurrent_unordered_map<std::string, ModelState> model_cache_;
    };
} // namespace solar::dnn::openvino
